#!/usr/bin/perl

#system("export NF2_DESIGN_DIR=/root/NF2/projects/packet_generator");

#folders
$root_folder="/root/switch_project";
$result_folder="$root_folder/experiment/exp12"; #root dir to store experimental resutls
$aggregated_result="$result_folder/total_result.txt"; #results for all experiments, used for plot

#input traffic file for netFPGA
$inpcap="$root_folder/traffic/nf2_dag1.pcap"; #input pcap file
$inpcap_flow2="$root_folder/traffic/nf3_dag1.pcap"; #input pcap file for 2nd flow

$runs=2; # number of repeated experiment (same setting)
$iteration=10; #number of iteration for packet transmission in netFPGA
$iteration_flow2=$iteration*20; #number of iteration for packet transmission in netFPGA to dag2, need to ensure finish transmission after flow to dag1
$flow2_sending_rate = 1000;
$flow2_rate = $flow2_sending_rate*1000; #1Gb/s

#used to calculate gap (not used now)
$packet_size=64; #byte
$number_of_packets=10*$iteration; #because nf2_dag1.pcap has 10 packets
@speed;
@gap;

#specify sending rate
$start_sending_rate=100;#Mb/s
$end_sending_rate=1000;
$sending_rate_gap=100;

#calculate speed and gap (gap is not used for now)
for($b=$start_sending_rate, $a=0; $b<=$end_sending_rate; $b+=$sending_rate_gap, $a++)
{
	$speed[$a]=$b;
	$gap[$a]=getInterFrameGap($speed[$a], $packet_size, $number_of_packets);
	print "\n speed = $speed[$a], gap = $gap[$a]\n";
}

#disable broadcast
##system("dagflood -f $root_folder/traffic/dag1_nf2 -d dag0 -c 1");

#run experiment
#j-control sending rate from netfpga to dag1, 
#i-control runs of experiments for same setting
##for($j=0; $j<=$#speed; $j++)
##{
##	for($i=1; $i<=$runs; $i++)
##	{
#create folder according to sending rate and index of run
##		print("$result_folder/$speed[$j]M/$i\n");
##		mkdir "$result_folder/$speed[$j]M";
##		mkdir "$result_folder/$speed[$j]M/$i";
##		chdir "$result_folder/$speed[$j]M/$i";

##		system("dagsnap -d0:0 -o 1.erf &");
##		system("dagsnap -d0:2 -o 2.erf &");
##		$rate = $speed[$j]*1000;
##		system("packet_generator.pl -q0 $inpcap -r0 $rate -i0 $iteration -q1 $inpcap -r1 $rate -i1 $iteration -q2 $inpcap_flow2 -r2 $flow2_rate -i2 $iteration_flow2");
#clean up
##		system("killall dagsnap");
##		sleep 2;
##	}
##}


#post-process data
for($j=0; $j<=$#speed; $j++)
{
	for($i=1; $i<=$runs; $i++)
	{
		chdir "$result_folder/$speed[$j]M/$i";
#processing erf
		system("dagbits -vf 1.erf decode |grep \'dst=\\|ts=\\|19 82 01 12 19 82 01 12\' > 1erf_grep.txt");
		system("dagbits -vf 2.erf decode |grep \'ts=\\|19 82 01 12 19 82 01 12\' > 2erf_grep.txt");

		simplify_grepped_erf_2flows("1erf_grep.txt", "flow_info.csv");
		simplify_grepped_erf_ref_flow("2erf_grep.txt", "ref_flow_info.csv");
	
		$file_name="1_flow_info.csv";
		if(-e $file_name)
		{
			compute_table("1_flow_info.csv", "ref_flow_info.csv", "1_flow_table.csv");
		}
		$file_name="2_flow_info.csv";
		#if(-e $file_name)
		#{
			#compute_table("2_flow_info.csv", "ref_flow_info.csv", "2_flow_table.csv");
		#}

#clean up
		#system("rm -f 1erf_grep.txt");
		#system("rm -f 2erf_grep.txt");
	}
}

chdir "$root_folder/script";

#process timestamp, seq number, and dst mac
#output format <flow#, seq#, timestamp#, total seq#>
sub simplify_grepped_erf_2flows
{
	my($in)=$_[0];
	my($out)=$_[1];
	open(IN, $in) or die "$in cannot be opened.\n";

	my($is_flow1_open)=0;
	my($is_flow2_open)=0;
	my($counter)=0;

	while(<IN>)
	{
		my($line)=$_;
		chomp($line);

		if($line =~ m/^(ts=)/) #timestamp
		{
			@block1=split(' ', $line);
			@block2=split(':', $block1[2]);
			$time = $block2[2]+$block2[1]*60+$block2[0]*3600;
		}	

		elsif($line =~ m/src=00:4e:46:32:43:01/) #src mac = flow1
		{
			#@block1=split(' ', $line);
			#$srcMac=$block1[1];
			$srcMac=1;
			if($is_flow1_open == 0)
			{
				open(OUT1, ">1_$out") or die "1_$out cannot be opened.\n";
				$is_flow1_open = 1;
			}
			#print OUT "$block1[1]\n";
		}
		elsif($line =~ m/src=00:4e:46:32:43:02/) #src mac = flow2
		{
			#@block1=split(' ', $line);
			#$srcMac=$block1[1];
			$srcMac=2;
			if($is_flow2_open == 0)
			{
				open(OUT2, ">2_$out") or die "2_$out cannot be opened.\n";
				$is_flow2_open = 1;
			}
			#print OUT "$block1[1]\n";
		}		
		elsif($line =~ m/(19 82 01 12 19 82 01 12)/) #seq number, and ready to output
		{
			@block1=split(' ', $line);
			$hex_value=$block1[0] . $block1[1];
			$dec_value=hex($hex_value);
			#print OUT "$dec_value\n";
			$counter=$counter+1;			
			
			if($srcMac == 1)
			{
				print OUT1 "$srcMac, $dec_value, $time, $counter\n";
			}
			elsif($srcMac == 2)
			{
				print OUT2 "$srcMac, $dec_value, $time, $counter\n";
			}
		}
		
	}

	close(IN);
	close(OUT1);
	close(OUT2);
}

#process timestamp, seq number
#output format <seq#, timestamp#>
sub simplify_grepped_erf_ref_flow
{
	my($in)=$_[0];
	my($out)=$_[1];
	open(IN, $in) or die "$in cannot be opened.\n";
	open(OUT, ">$out") or die "$out cannot be opened.\n";

	while(<IN>)
	{
		my($line)=$_;
		chomp($line);

		if($line =~ m/^(ts=)/) #timestamp
		{
			@block1=split(' ', $line);
			@block2=split(':', $block1[2]);
			$time = $block2[2]+$block2[1]*60+$block2[0]*3600;
		}			
		elsif($line =~ m/(19 82 01 12 19 82 01 12)/) #seq number, and ready to output
		{
			@block1=split(' ', $line);
			$hex_value=$block1[0] . $block1[1];
			$dec_value=hex($hex_value);		
			
			print OUT "$dec_value, $time\n";
		}
		
	}

	close(IN);
	close(OUT);
}

#output format <flow#, seq#, received_timestamp, delay/loss, seq#_in_all_flows>
sub compute_table
{
	my($in_flow)=$_[0];
	my($in_ref)=$_[1];
	my($out)=$_[2];

	open(IN_FLOW, $in_flow) or die "$in_flow cannot be opened.\n";
	open(IN_REF, $in_ref) or die "$in_ref cannot be opened.\n";
	open(OUT, ">$out") or die "$out cannot be opened.\n";

	$line_flow = <IN_FLOW>;
	chomp($line_flow);
	@flow_block=split(', ', $line_flow);
	$flow_num=$flow_block[0];
	$seq_flow=$flow_block[1];		
	$timestamp_flow=$flow_block[2];
	$total_seq_flow=$flow_block[3];
	#print "begin, flow_num =$flow_num,  seq_flow = $seq_flow, timestamp_flow=$timestamp_flow,  total_seq_flow=$total_seq_flow\n";

	while($line_ref = <IN_REF>)
	{
		chomp($line_ref);
		#print("line_ref = $line_ref\n");
		
		@ref_block=split(', ', $line_ref);
		$seq_ref=$ref_block[0];
		$timestamp_ref=$ref_block[1];

		#print "seq_ref = $seq_ref,  timestamp_ref = $timestamp_ref\n";

		if($seq_ref == $seq_flow)#no loss
		{
			$delay = $timestamp_flow - $timestamp_ref;
			$delay = $delay*(10**6); #convert to us
			$formatted_delay=sprintf("%.3f", $delay);

			print OUT "$flow_num, $seq_ref, $timestamp_flow, $formatted_delay, $total_seq_flow\n";
			#print "found a match, delay=$delay, flow_num =$flow_num,  seq_flow = $seq_flow, timestamp_flow=$timestamp_flow,  total_seq_flow=$total_seq_flow\n";

			#go to next record in flow
			$line_flow = <IN_FLOW>;
			chomp($line_flow);
			#print("line_flow = $line_flow\n");
			if($line_flow!='') #last line can be empty
			{
				@flow_block=split(', ', $line_flow);
				#$flow_num=$flow_block[0];
				$seq_flow=$flow_block[1];		
				$timestamp_flow=$flow_block[2];
				$total_seq_flow=$flow_block[3];				
			}
			else
			{
				last;
			}
			#print "next of a match, delay=$delay, flow_num =$flow_num,  seq_flow = $seq_flow, timestamp_flow=$timestamp_flow,  total_seq_flow=$total_seq_flow\n";

		}
		else
		{
			$delay = 0; #loss
			print OUT "$flow_num, $seq_ref, -1, $delay, -1\n";
			#print "no match, seq_ref = $seq_ref,  timestamp_ref = $timestamp_ref, seq_flow = $seq_flow, timestamp_flow=$timestamp_flow\n";
		}
	}

	close(IN_FLOW);
	close(IN_REF);
	close(OUT);
}

#arguments: 1. sending rate(Mb/s), 2. packet size(Byte) 3. number of packets
sub getInterFrameGap
{
	my($sending_rate)=$_[0];
	my($pk_size)=$_[1];
	my($num_of_packets)=$_[2];	
	#print("$sending_rate, $pk_size, $number_of_packets\n");

	my($bandwidth)=10**9;
	my($interframe_gap); #ns
	my($formatted_ifg);

	$interframe_gap=(($pk_size*8*$num_of_packets/$sending_rate/(10**6))-($pk_size*8/$bandwidth))/($num_of_packets-1) * (10**9);
	#print("interframe gap = $interframe_gap\n");
	
	$formatted_ifg=sprintf("%.0f", $interframe_gap);
	return $formatted_ifg;
}

#only up to day, be careful when doing experiment in midnight :)
#argument 1. input file after dagbits 2. output file
sub compute_timestamp
{
	my($in)=$_[0];
	my($out)=$_[1];

	open(IN, $in) or die "$in cannot be opened.\n";
	open(OUT, ">$out") or die "$out cannot be opened.\n";

	while(<IN>)
	{
		my($line)=$_;
		chomp($line);

		@block1=split(' ', $line);
		#print "$block1[2]\n";
		@block2=split(':', $block1[2]);
		#print "$block2[0] $block2[1] $block2[2]\n";
		$time = $block2[2]+$block2[1]*60+$block2[0]*3600;
		print OUT "$time\n";
		#print "$time\n";
	}

	close(IN);
	close(OUT);
}
